/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package irsystem.scenario;

import irsystem.collection.CISI;
import irsystem.collection.CISIQuery;
import irsystem.scenario.method.AugmentedTF;
import irsystem.scenario.method.BinaryTF;
import irsystem.scenario.method.DocumentRank;
import irsystem.scenario.method.InvertedFile;
import irsystem.scenario.method.LogarithmicTF;
import irsystem.scenario.method.NIAP;
import irsystem.scenario.method.Normalization;
import irsystem.scenario.method.RawTF;
import irsystem.scenario.method.StemmerNotMaul;
import irsystem.scenario.method.StopwordRemoval;
import irsystem.scenario.method.TermFrequency;
import irsystem.scenario.method.TermVectorSpace;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

/**
 *
 * @author User
 */
public class QueryScenario {
    // skenario experiment
    
    ScenarioOption option;
    ExperimentResult result;
    CISI cisi;
    InvertedFile invertedFile;
    private String queryString;
    

    public QueryScenario(ScenarioOption option, CISI collection, InvertedFile invertedFile, String queryString)
    {
        this.option = option;
        this.cisi=collection;
        this.invertedFile=invertedFile;
        this.queryString=queryString;
    }
    
    public void startScenario()
    {
        result=new ExperimentResult();
        
        // proses dokumen, bikin inverted file ato baca
        // udah lah ya...
        if(invertedFile==null)
        {
            if(new File("inverted.tmp").exists())
            {
                invertedFile=InvertedFile.loadFromFIle("inverted.tmp");
                if(invertedFile!=null)
                {
                    if(option.equals(invertedFile.getOption())==false)
                    {
                        invertedFile=null;
                    }
                }
            }
            if(invertedFile==null)
            {
                invertedFile=new InvertedFile(option, cisi);
                long cur=System.currentTimeMillis();
                System.out.println(cur);
                invertedFile.process();
                System.out.println(System.currentTimeMillis()-cur);
                //invertedFile.saveToFile("inverted.tmp");
            }
        }
        
        // proses per query
            
            
            List<String> queryArrays=new ArrayList<String>();
            Collections.addAll(queryArrays, queryString.split("\\s+"));
            
            // Stopword...
            if(option.isUseStopword())
            {
                StopwordRemoval removal=new StopwordRemoval(queryArrays, cisi);
                queryArrays=removal.process();
            }
            
            // Stemming...
            if(option.isUseStemming())
            {
                // pake stemming, sok lah...
                StemmerNotMaul stemming=new StemmerNotMaul(queryArrays);
                queryArrays=stemming.process();                
            }
            
            // Term Weighting
            TermFrequency tf=null;
            TermVectorSpace termFrequencyEntries=null;
            switch(option.getTermFrequency())
            {
                case ScenarioOption.TF_RAW:
                    tf=new RawTF(queryArrays);
                    break;
                case ScenarioOption.TF_BINARY:
                    tf=new BinaryTF(queryArrays);
                    break;
                case ScenarioOption.TF_AUGMENTED:
                    tf=new AugmentedTF(queryArrays);
                    break;
                case ScenarioOption.TF_LOGARITHMIC:
                    tf=new LogarithmicTF(queryArrays);
                    break;
            }
            
            termFrequencyEntries=tf.process();
            TermVectorSpace tf_idf=termFrequencyEntries;
            
            TermVectorSpace idfEntries=new TermVectorSpace(new HashMap<String, Double>());
            // Inverse Document Frequency
            if(option.isUseIDF())
            {
                // idf ambil dari inverted file ajah..
                Iterator<Entry<String,Double>> it=termFrequencyEntries.getVector().entrySet().iterator();
                while(it.hasNext())
                //for(String term:new HashSet<String>(termFrequencyEntries.getVector().keySet()))
                {
                    Entry<String,Double> entry=it.next();
                    String term=entry.getKey();
                    Double idf=0.0;
                    if(invertedFile.containTerm(term))
                    {
                        idf=invertedFile.getEntry(term).getIdf();
                    }
                    idfEntries.addValue(term, idf);
                }
                tf_idf=termFrequencyEntries.elementProduct(idfEntries);
            }
            
            // normalisasi
            if(option.isUseNormalization())
            {
                Normalization norm=new Normalization(tf_idf);
                tf_idf=norm.process();
            }
            
            DocumentRank ranks=new DocumentRank();
            
            // similarity test...
            for(String term:new HashSet<String>(tf_idf.getVector().keySet()))
            {
                if(invertedFile.containTerm(term))
                {
                    List<Integer> docID=invertedFile.getEntry(term).getDocID();
                    DocumentRank.RankEntry entry;
                    for(int k=0;k<docID.size();k++)
                    {
                        if(ranks.containDocID(docID.get(k)))
                        {
                            entry=ranks.getRankEntry(docID.get(k));
                        }
                        else
                        {
                            entry=new DocumentRank.RankEntry(docID.get(k), 0.0);
                            ranks.addEntry(entry);
                        }
                        entry.setSimilarity(entry.getSimilarity()+invertedFile.getEntry(term).getTf_idf().get(k));
                    }
                }
            }
            
//            // untuk per dokumen
//            List<TermVectorSpace> docVectorArrays=new ArrayList<TermVectorSpace>();
//            for(int j=0;j<cisi.getDocs().size();j++)
//            {
//                List<String> docArrays=new ArrayList<String>();
//                Collections.addAll(docArrays,cisi.getDocs().get(j).getWords().split("\\s+"));
//                // Stopword...
//                if(option.isUseStopword())
//                {
//                    StopwordRemoval removal=new StopwordRemoval(docArrays, cisi);
//                    docArrays=removal.process();
//                }
//
//                // Stemming...
//                if(option.isUseStemming())
//                {
//                    // pake stemming, sok lah...
//                    StemmerNotMaul stemming=new StemmerNotMaul(docArrays);
//                    docArrays=stemming.process();                
//                }
//                
//                TermVectorSpace docVector=documentWeighting(docArrays);
//                docVectorArrays.add(docVector);
//            }
//            
//            // similarity test
//            TermVectorSpace queryVector=queryWeighting(queryArrays);
//            for(int j=0;j<cisi.getDocs().size();j++)
//            {
//            
//                double product=queryVector.dotProduct(docVectorArrays.get(j));
//                if(product!=0)
//                {
//                    DocumentRank.RankEntry entry=new DocumentRank.RankEntry(j+1, product);
//                    ranks.addEntry(entry);
//                }
//            }
            
            ranks.sort();
            // sama hitung NIAP
            List<Integer> retrieved=ranks.getDocIDs();
            List<Integer> relevant=retrieved;
            NIAP niap=new NIAP(retrieved, relevant);
            double niapval=niap.process();
            result.addResult(0, retrieved, niapval);
    }

    public ExperimentResult getResult()
    {
        return result;
    }

    public ScenarioOption getOption()
    {
        return option;
    }

    public void setOption(ScenarioOption option)
    {
        this.option = option;
    }

    public CISI getCisi()
    {
        return cisi;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }
}
